package server

import (
	"context"
	"encoding/json"
	"fmt"
	"longmen/server/config/global"
	"longmen/server/pkg/common/helper/timehelper"
	utils2 "longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	pb "longmen/server/pkg/protobuf"

	"longmen/server/pkg/common/api_models"

	"github.com/jinzhu/copier"
	"github.com/labstack/echo/v4"
)

func (s *Server) GetUserInfo(ctx context.Context, req *pb.GetUserInfoReq) (*pb.GetUserInfoResp, error) {

	userid := int(req.GetUid())
	user, err := s.GetUserById(userid)
	if err != nil {
		return nil, err
	}
	resp := new(pb.GetUserInfoResp)
	resp.Account = user.Account
	resp.NickName = user.NickName
	resp.Avatar = user.Avatar
	resp.Diamond = uint32(user.Diamond)
	resp.Mobile = user.Mobile
	resp.Gold = uint32(user.Gold)
	resp.ReceiveVip = uint32(user.ReceiveVip)
	noticeTime, err := s.getLatestNotice(user.Id)
	if err != nil {
		return nil, err
	}
	if noticeTime > user.ReadTime.Unix() {
		resp.HasNotice = true
	}
	//关注数量
	resp.AttentCount = uint32(len(cache.GetUserAttentAnchorIds(user.Id)))
	//粉丝数量
	resp.FansCount = uint32(cache.GetFansCount(user.Id))
	//送礼数量
	resp.GiftSpend = uint32(cache.GetSendGiftCount(user.Id))
	//用户资料
	profile, err := s.getUserProfile(userid)
	if err != nil {
		return nil, err
	}
	resp.Sex = uint32(profile.Gender)
	level, err := s.getUserLevel(user.Point) //用户经验值查询对应等级
	if err != nil {
		return nil, err
	}
	record, err := db_main.GetNobleRecordByUid(userid)
	if err != nil {
		return nil, err
	}
	resp.NobleId = uint32(record.NobleId)
	// 用户开通过VIP，且没有到期
	if record.Id > 0 {
		resp.RankId = uint32(record.RankId)
		resp.VipName = record.Name
		resp.VipLeftDay = getLeftDays(record.Expiration)
		resp.GiftDiscount = int32(record.GiftDiscount)
	}

	err = copier.Copy(resp, level) // 对象拷贝等级信息
	if err != nil {
		return nil, err
	}
	if user.Password != "" {
		resp.HasPassword = true
	}

	//// 用户没有开通VIP，已经领取VIP盲盒的时候返回领取VIP信息
	//if user.ReceiveVip > 0 && record.NobleId == 0 {
	//nobleRecord, err2 := repository.GetNobleRecordByUid(userid)
	//	if err2 == nil {
	//		//resp.RankId = uint32(nobleRecord.RankId)//fixme
	//		//resp.VipName = nobleRecord.Name
	//		resp.VipLeftDay = getLeftDays(nobleRecord.Expiration)
	//	} else {
	//		return nil, err
	//	}
	//}
	resp.IsGuessHost = uint32(user.IsGuessHost)
	resp.TDeactive = user.DeactiveTime.Format("2006-01-02 15:04")
	resp.Status = uint32(user.Status)
	//增加坐骑
	propsItem := db_main.GetProps(req.GetUid())
	copier.Copy(resp.Item, propsItem)

	return resp, nil
}

func (s *Server) GetLevelAndNoble(user *models_main.PartUser) (*pb.GetUserInfoResp, error) {
	resp := new(pb.GetUserInfoResp)
	record, err := db_main.GetNobleRecordByUid(user.Id)
	if err != nil {
		return nil, err
	}
	level, err := s.getUserLevel(int(user.Point)) //用户经验值查询对应等级
	if err != nil {
		return nil, err
	}
	resp.NobleId = uint32(record.NobleId)
	resp.Level = uint32(level.Level)
	return resp, nil
}

func getLeftDays(et_tamp int64) uint32 {
	//str := "2022-08-08 13:35:32"
	//end := "2022-08-08 13:39:32"
	//
	//loc, _ := timehelper.LoadLocation(util.DEFAULT_LOCATION_STR)
	//st, _ := timehelper.ParseInLocation(util.TIME_LAYOUT_FORMAT_1, str, loc)
	//et, _ := timehelper.ParseInLocation(util.TIME_LAYOUT_FORMAT_1, end, loc)

	//st_tamp := st.Unix()
	//et_tamp := et.Unix()

	st_tamp := timehelper.GetTimeStamp(1) //得到当前以秒为单位的timeStamp
	if st_tamp >= et_tamp {               //start 和end的距离
		return 0
	}
	// 按秒算
	left_day := (et_tamp - st_tamp) / 86400
	return uint32(left_day + 1) //只要是多1秒就算1天
}

func (s *Server) GetUserById(uid int) (*models_main.User, error) {
	result, err := cache.GetUserFullInfo(uid)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// getLatestNotice 最后阅读消息通知时间
func (s *Server) getLatestNotice(uId int) (int64, error) {
	list, err := s.getNoticeList(uId, 1, 1)
	if err != nil {
		return 0, err
	}

	var creatTime int64
	for _, notice := range list.GetNoticeLsit {
		creatTime = notice.CreateTime
		break
	}
	return creatTime, err
}

func (s *Server) getUserProfile(id int) (*models_main.UserProfile, error) {
	return db_main.GetUserProfileParam(map[string]interface{}{"uid": id})
}

/* 包内部使用的方法，请用小写字母打头 */
// getNoticeList
func (s *Server) getNoticeList(uId, page, size int) (*pb.GetNoticeListResp, error) {
	var (
		condition = echo.Map{
			"or": []interface{}{"user_id = ? or user_id = 0", uId},
		}
	)

	//// 当前用户的站内通知
	//exclusiveList, err := repository.GetNoticeList(echo.Map{"user_id": uId}, page, size)
	//if err != nil {
	//	return nil, err
	//}
	//
	//// 所有用户的站内通知
	//commonList, err := repository.GetNoticeList(echo.Map{"user_id": 0}, page, size)
	//if err != nil {
	//	return nil, err
	//}

	//List := append(exclusiveList, commonList...)

	List, err := db_main.GetNoticeList(condition, page, size)
	if err != nil {
		return nil, err
	}

	var noticeList []*pb.GetNoticeList
	for _, v := range List {
		noticeList = append(noticeList, &pb.GetNoticeList{
			ImageUrl:   v.ImageUrl,
			CreateTime: v.CreatedAt.Unix(),
			Content:    v.Content,
			Link:       v.Link,
		})
	}

	return &pb.GetNoticeListResp{
		GetNoticeLsit: noticeList,
	}, nil
}

// 取默认头像列表，从缓存中取
func (s *Server) GetDefultAvatars(ctx context.Context, req *pb.GetDefultAvatarsReq) (*pb.GetDefultAvatarsResp, error) {
	list := []models_main.Avatars{}
	sAvatars := cache.GetDefultAvatars()
	if len(sAvatars) > 0 {
		err := json.Unmarshal([]byte(sAvatars), &list)
		if err != nil {
			global.Log.Error(err)
			return nil, err
		}
	}
	slice := make([]*pb.DefultAvatar, 0)
	for _, avatar := range list {
		if req.Role <= 1 && avatar.RoleType != 1 { //如果要的是用户或为0，那专家的不给
			continue
		}
		slice = append(slice, &pb.DefultAvatar{
			Id:       int64(avatar.Id),
			ImageUrl: avatar.ImageUrl,
		})
	}
	return &pb.GetDefultAvatarsResp{
		DefultAvatar: slice,
	}, nil
}

func (s *Server) calculateUserLevel(point uint32) ([]*models_main.UserLevelRule, uint8, error) {
	var (
		err   error
		level uint8
		fName = "CalculateUserLevel"
		rule  []*models_main.UserLevelRule
	)

	if rule, err = cache.GetUserLevelRule(); err != nil {
		return nil, 0, fmt.Errorf("%s %s", utils2.Convert(fName), err.Error())
	}

	for i := 0; i < len(rule)-1; i++ {
		for j := 0; j < len(rule)-1-i; j++ {
			if rule[j].Level > rule[j+1].Level {
				rule[j], rule[j+1] = rule[j+1], rule[j]
			}
		}
	}

	for i := 0; i < len(rule); i++ {
		if point >= rule[i].Point {
			level = rule[i].Level
		} else {
			break
		}
	}

	return rule, level, nil
}

func (s *Server) getUserLevel(userPoint int) (*api_models.Level, error) {
	fName := "GetUserLevel"
	var upgradePoint uint32 //指定等级所需经验
	var process uint32      //当前等级进度
	var difference uint32   //获取用户经验值,计算出level
	var remainder uint32    //获取用户经验值,计算出level
	rule, level, err := s.calculateUserLevel(uint32(userPoint))
	if err != nil {
		return nil, fmt.Errorf("%s%s", utils2.Convert(fName), err)
	}

	for i := 0; i < len(rule); i++ {
		if level == rule[i].Level-1 {
			upgradePoint = rule[i].Point
			if i > 0 {
				process = uint32(userPoint - int(rule[i-1].Point))
				difference = rule[i].Point - rule[i-1].Point
				break
			}
			process = uint32(userPoint) //0级别
			difference = rule[i].Point
			break
		}
	}

	if upgradePoint > uint32(userPoint) {
		remainder = upgradePoint - uint32(userPoint)
	}

	return &api_models.Level{
		Level:        level,
		Point:        uint32(userPoint),
		UpgradePoint: upgradePoint,
		Process:      process,
		Difference:   difference,
		Remainder:    remainder,
	}, nil
}
